<!-- @format -->

<template>
  <div class="app">
    <wd-navbar fixed placeholder safeAreaInsetTop :bordered="false">
      <template #left>
        <view class="nav-left">
          <the-capsule class="ml-16"></the-capsule>
          <view class="ml-16" @click="onRefresh(false)">
            <view
              class="icon-x"
              :style="iconStyl"
              :class="{ rotate: refreshing }"
            >
              <wd-icon name="refresh" />
            </view>
          </view>
          <!-- 收藏一下 -->
          <the-icon
            class="ml-16"
            v-if="hasFav"
            :icon="favIconName"
            @click="onFav"
          ></the-icon>

          <!-- 热门项目 -->
          <the-icon
            v-if="isAdmin"
            class="ml-16"
            :icon="collectIconName"
            @click="onCollect"
          ></the-icon>
        </view>
      </template>
    </wd-navbar>
    <view class="content">
      <div class="app-header">
        <div class="app-header-title">
          <h1 class="app-title">{{ config.name }}</h1>
          <!-- <view @click="navigateToRepositories" class="repository-entry">
            <wd-icon name="folder" />
            <span style="padding-left: 4px">我的</span>
          </view> -->
        </div>
        <div v-if="config.desc" class="app-desc">{{ config.desc }}</div>
      </div>

      <tree-menu v-if="!contentEmpty" :tree="fileTree" @select="onSelect" />
      <wd-status-tip v-else-if="!loading" image="content" tip="列表为空" />
    </view>
    <div v-if="loading" class="loading-container">
      <base-loading message="内容加载中..." />
    </div>
    <div v-else-if="error" class="error-container">
      <wd-notice-bar :text="error" type="danger" />
    </div>
    <wd-toast />
  </div>
</template>

<script lang="ts" setup>
import { onLoad, onShareAppMessage } from '@dcloudio/uni-app'
import { computed, onMounted, ref } from 'vue'
import { useToast } from 'wot-design-uni'
import BaseLoading from '../../components/BaseLoading.vue'
import { useBook } from '../../composables/useBook'
import { useCache } from '../../composables/useCache'
import { useHotBook } from '../../composables/useHotBook'
import { useUserService } from '../../composables/useUserService'
import { USER_CONF } from '../../contants/configCont'
import { GiteeService } from '../../services/giteeService'

interface Config {
  owner: string
  repo: string
  name: string
  share: {
    title: string | string[]
  }
  [key: string]: string | Config['share']
}

const toast = useToast()

const config = ref<Config>({} as Config)
const giteeService = new GiteeService()
const loading = ref(true)
const error = ref<string | null>(null)
const fileTree = ref<any>([])
const refreshing = ref(false)
const iconStyl = ref({})

const { getMarkdownFiles } = useBook()
let refreshTime = 0
const contentEmpty = computed(() => {
  return !fileTree.value || !fileTree.value.length
})

const { isAdmin, addRes, resHasCheck, updateUserConf } = useUserService()

const { toggleHotBook, checkIsExist } = useHotBook({ mounted: isAdmin.value })

const favIconName = computed(() => {
  const cf = config.value
  const result = resHasCheck(cf.owner, cf.repo)
  return result ? 'star-filled' : 'star'
})

const collectIconName = computed(() => {
  const cf = config.value
  const result = checkIsExist({ owner: cf.owner, repo: cf.repo })
  return result ? 'heart-filled' : 'heart'
})

const hasFav = computed(() => {
  return config.value.fav
})

const initConfig = (params) => {
  const {
    owner = USER_CONF.owner,
    repo = USER_CONF.repo,
    name = USER_CONF.name,
    ...rest
  } = params || {}
  config.value = {
    owner,
    repo,
    name,
    ...rest,
  }
}

const onSelect = (data) => {
  const { path, url } = data
  const cf = config.value || ({} as Config)
  let query = ''
  if (url) {
    query = `url=${url}`
  } else {
    query = `owner=${cf.owner}&repo=${cf.repo}&path=${path}`
  }
  uni.navigateTo({
    url: `/pages/article/detail?${query}`,
  })
}

const loadFiles = async (refresh = false) => {
  try {
    const cf = config.value || { owner: 'tunie', repo: 'handbook' }
    const key = `tree-${cf.owner}-${cf.repo}`
    const cache = useCache<any>(key, -1)
    if (!refresh) {
      const cachedData = cache.getItem()
      if (cachedData) {
        if (Array.isArray(cachedData)) {
          fileTree.value = cachedData
        } else {
          config.value = { ...config.value, ...cachedData.config }
          fileTree.value = cachedData.files
        }
        return
      }
    }

    const files = await getMarkdownFiles(cf.owner, cf.repo)

    config.value = { ...config.value, fav: false, ...files._config }
    // const treeData = buildTree(files)
    fileTree.value = files
    cache.setItem({ config: files._config, files }) // 缓存数据
  } catch (err) {
    error.value = '加载文件失败'
    console.error(err)
  } finally {
    loading.value = false
  }
}

const sharePath = computed(() => {
  const query = ['owner', 'repo', 'name']
    .map((key) => `${key}=${config.value[key]}`)
    .join('&')
  return `/pages/index/index?${query}`
})

const onRefresh = async (showTip = true) => {
  if (loading.value) return

  refreshing.value = true
  refreshTime = Date.now()
  await loadFiles(true)
  showTip && toast.show('更新成功')
  refreshFinish()
}

const onFav = () => {
  const { owner, repo, name, desc } = config.value
  addRes({
    toast,
    owner,
    repo,
    name,
    desc,
  })
}

const onBacktop = async () => {
  await updateUserConf({ homePath: sharePath.value })
  toast.show('设置成功')
}

const onCollect = () => {
  const { owner, repo, name, desc } = config.value
  toggleHotBook({
    owner,
    repo,
    name,
    desc,
  })
}

const refreshFinish = () => {
  if (!refreshing.value) return
  const current = (((Date.now() - refreshTime) % 1000) * 360) / 1000
  iconStyl.value = { transform: `rotate(${current}deg)` }
  refreshing.value = false
  setTimeout(() => {
    iconStyl.value = { transform: 'rotate(360deg)' }
  }, 60)
}

const navigateToRepositories = () => {
  uni.navigateTo({
    url: '/pages/repositories/repositories',
  })
}

onLoad((params) => {
  initConfig(params)
})

onMounted(() => {
  loadFiles()

  setTimeout(() => onRefresh(false), 0)
})

const getShareTitle = () => {
  let title = config.value.share.title
  if (Array.isArray(title)) {
    title = title[Math.floor(Math.random() * title.length)]
  }

  return title || '这是一个朴实无华的分享'
}

onShareAppMessage(() => {
  return {
    title: getShareTitle(),
    path: sharePath.value,
  }
})
</script>

<style scoped>
.content {
  padding: 20px;
}
.app-header {
  padding: 40rpx 0 40rpx;
  margin-bottom: 12px;
  border-bottom: 1px solid #eaecef;
  /* background-color: #fff; */
}

.app-header-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.app-title {
  font-size: 24px;
  font-weight: 600;
  color: #2c3e50;
}

.app-desc {
  padding-top: 10rpx;
  color: #666;
}

.loading-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 200px;
}

.icon-x {
  display: inline-block;
  transition: transform 0.4s linear;
  transform: rotate(0deg);
}

.rotate {
  animation: rotate 1s linear infinite;
}

.nav-left {
  display: flex;
  align-items: center;
}

.ml-16 {
  margin-right: 16rpx;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.repository-entry {
  display: flex;
  align-items: center;
  cursor: pointer;
}
</style>
